﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.IO;//
using Xbim.Ifc;
using Xbim.ModelGeometry.Scene;//
using Xbim.Common.Step21;
using Xbim.Common;
using Xbim.Ifc4.Kernel;
using Xbim.Ifc4.SharedBldgElements;
using Xbim.Ifc4.PropertyResource;
using Xbim.Ifc4.MeasureResource;
using Xbim.Ifc4.Interfaces;

namespace xBimServer.Controllers
{
    /// <summary>
    /// 弃用
    /// </summary>
    public class xBimController : Controller
    {
        // GET: xBim


        public ActionResult GetIFCInfo(string wFileName)
        {
            string fileName = Server.MapPath(@"\res\ifc\Ghasem.ifc");
            if (!string.IsNullOrEmpty(wFileName))
            {
                fileName = Server.MapPath(wFileName);
            }

            #region  
            var lsInfo = new List<string>();
            using (var model = IfcStore.Open(fileName))
            {
                //get all doors in the model (using IFC4 interface of IfcDoor this will work both for IFC2x3 and IFC4)
                var allDoors = model.Instances.OfType<IIfcDoor>();

                var someDoors = model.Instances.Where<IIfcDoor>(d => d.IsTypedBy.Any()).ToList();
                someDoors.ForEach(theDoor =>
                {
                    var properties = theDoor.IsDefinedBy
                        .Where(r => r.RelatingPropertyDefinition is IIfcPropertySet)
                        .SelectMany(r => ((IIfcPropertySet)r.RelatingPropertyDefinition).HasProperties)
                        .OfType<IIfcPropertySingleValue>();
                    foreach (var property in properties)
                    {
                        lsInfo.Add($"{property.Name}: '{property.NominalValue}'");
                    }

                });


            }

            #endregion

            return Json(lsInfo, JsonRequestBehavior.AllowGet);
        }
        /// <summary>
        /// 获取所有空间信息
        /// </summary>
        /// <param name="wFileName"></param>
        /// <returns></returns>
        public ActionResult GetAllSpaces(string wFileName)
        {
            string fileName = Server.MapPath(@"\res\ifc\Ghasem.ifc");
            if (!string.IsNullOrEmpty(wFileName))
            {
                fileName = Server.MapPath(wFileName);
            }

            #region  
            var lsInfo = new List<string>();
            using (var model = IfcStore.Open(fileName))
            {
                //获取模型中的所有空间. 
                var spaces = model.Instances.OfType<IIfcSpace>().ToList();

                foreach (var space in spaces)
                {
                    lsInfo.Add($"空间名：{space?.Name}");
                    // 获得包含空间的楼层
                    var floor = GetFloor(space);
                    lsInfo.Add($"楼层名：{floor?.Name}");
                    // 获取面积
                    var area = GetArea(space);
                    if (area != null)
                    {
                        var strValue = "";
                        // 如果来自属性而不是数量，那么僵不能保证它是数字
                        if (area.UnderlyingSystemType == typeof(double))
                        {
                            var numValue = (double)(area.Value);
                            strValue = numValue.ToString();
                        }
                        else
                        {
                            strValue = area.ToString();
                        }
                        lsInfo.Add($"面积：{strValue}");
                    }
                    // 获取体积
                    var volume = GetVolume(space);
                    if (volume != null)
                    {
                        var strValue = "";
                        // 如果来自属性而不是数量，那么将不能保证它是数字
                        if (volume.UnderlyingSystemType == typeof(double))
                        {
                            var numValue = (double)(volume.Value);
                            strValue = numValue.ToString();
                        }
                        else
                        {
                            strValue = volume.ToString();
                        }
                        lsInfo.Add($"体积：{floor?.Name}");
                    }
                }
            }

            #endregion

            return Json(lsInfo, JsonRequestBehavior.AllowGet);
        }

        #region 获取所有空间信息
        private static IIfcBuildingStorey GetFloor(IIfcSpace space)
        {
            return
                //获取所有对象化的关系，这些关系将按此空间进行分解
                space.Decomposes
                //选择分解的对象（这些对象可能是其他空间或建筑楼层）
                .Select(r => r.RelatingObject)
                //仅获取楼层 
                .OfType<IIfcBuildingStorey>()
                //获取第一个
                .FirstOrDefault();
        }
        private static IIfcValue GetArea(IIfcProduct product)
        {
            //尝试先从数量中获取
            var area =
                //获取可以定义属性和数量集的所有关系
                product.IsDefinedBy
                //在所有属性和数量集之间搜索。
                //您可能还希望按名称搜索特定数量
                .SelectMany(r => r.RelatingPropertyDefinition.PropertySetDefinitions)
                //数量集合
                .OfType<IIfcElementQuantity>()
                //从数量集获取所有数量
                .SelectMany(qset => qset.Quantities)
                //我们只对面积感兴趣 
                .OfType<IIfcQuantityArea>()
                //我们将采取第一个。显然有一个以上的面积属性
                //所以, 要检查的名称。但是,我们将保持它简单的这个例子。
                .FirstOrDefault()?
                .AreaValue;
            if (area != null)
                return area;
            //从属性中获取值
            return GetProperty(product, "Area");
        }
        private static IIfcValue GetVolume(IIfcProduct product)
        {
            var volume = product.IsDefinedBy
                .SelectMany(r => r.RelatingPropertyDefinition.PropertySetDefinitions)
                .OfType<IIfcElementQuantity>()
                .SelectMany(qset => qset.Quantities)
                .OfType<IIfcQuantityVolume>()
                .FirstOrDefault()?.VolumeValue;
            if (volume != null)
                return volume;
            return GetProperty(product, "Volume");
        }
        private static IIfcValue GetProperty(IIfcProduct product, string name)
        {
            return
                //获取可以定义属性和数量集的所有关系
                product.IsDefinedBy
                //在所有属性和数量集之间搜索。您可能还希望在特定属性集中搜索
                .SelectMany(r => r.RelatingPropertyDefinition.PropertySetDefinitions)
                //在这种情况下, 只考虑属性集。
                .OfType<IIfcPropertySet>()
                //从所有属性集中获取所有属性
                .SelectMany(pset => pset.HasProperties)
                //只允许考虑单个值属性。还有枚举属性,
                //表属性、引用属性、复杂属性和其他
                .OfType<IIfcPropertySingleValue>()
                .Where(p =>
                    string.Equals(p.Name, name, System.StringComparison.OrdinalIgnoreCase) ||
                    p.Name.ToString().ToLower().Contains(name.ToLower()))
                .FirstOrDefault()?.NominalValue;
        }
        #endregion
        /// <summary>
        /// 获取空间层次
        /// </summary>
        /// <param name="wFileName"></param>
        /// <returns></returns>
        public ActionResult GetAllStructures(string wFileName)
        {
            string fileName = Server.MapPath(@"\res\ifc\Ghasem.ifc");
            if (!string.IsNullOrEmpty(wFileName))
            {
                fileName = Server.MapPath(wFileName);
            }

            #region  
            using (var model = IfcStore.Open(fileName))
            {
                var project = model.Instances.FirstOrDefault<IIfcProject>();
                lsHierarchy = new List<string>();
                PrintHierarchy(project, 0);
            }

            #endregion

            return Json(lsHierarchy, JsonRequestBehavior.AllowGet);
        }

        #region   获取空间层次
        public static List<string> lsHierarchy = new List<string>();
        private static void PrintHierarchy(IIfcObjectDefinition o, int level)
        {
            
            lsHierarchy.Add(string.Format("{0}{1} [{2}]", GetIndent(level), o.Name, o.GetType().Name));
            // 只有空间元素可以包含建筑元素
            var spatialElement = o as IIfcSpatialStructureElement;
            if (spatialElement != null)
            {
                // 使用 IfcRelContainedInSpatialElement 获取包含的元素
                var containedElements = spatialElement.ContainsElements.SelectMany(rel => rel.RelatedElements);
                foreach (var element in containedElements)
                    lsHierarchy.Add(string.Format("{0}    ->{1} [{2}]", GetIndent(level), element.Name, element.GetType().Name));
            }

            // 使用 IfcRelAggregares 获取空间结构元素的空间分解
            foreach (var item in o.IsDecomposedBy.SelectMany(r => r.RelatedObjects))
            {
                PrintHierarchy(item, level + 1);
            }
        }

        private static string GetIndent(int level)
        {
            var indent = "";
            for (int i = 0; i < level; i++)
                indent += "  ";
            return indent;
        }
    }


    #endregion





}